﻿using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using Supermodel.Exceptions;

namespace Supermodel.MVC.FormModels
{
    public class DateTimeFormModel : IFormModelEntityMapper, IFormModelEditorTemplate, IFormModelDisplayTemplate, IFormModelModelBinder
    {
        public DateTimeFormModel()
        {
            Value = null;
        }
        
        public DateTime? Value { get; set; }

        public void MapFromEntityObject(object obj, Type objType)
        {
            if (objType != typeof(DateTime) && objType != typeof(DateTime?)) throw new FormModelPropertyCantBeAutomapedException(string.Format("{0} can't be automapped to {1}", GetType().Name, objType.Name));

            var domainObj = (DateTime?) obj;
            Value = domainObj;
        }

        public object MapToEntityObject(object obj, Type objType)
        {
            if (objType != typeof(DateTime) && objType != typeof(DateTime?)) throw new FormModelPropertyCantBeAutomapedException(string.Format("{0} can't be automapped to {1}", GetType().Name, objType.Name));

            return Value;
        }

        public bool GetIEditorTemplateImplemented() { return true; }
        public MvcHtmlString EditorTemplate(HtmlHelper html)
        {
            var dateTimeStr = (Value == null) ? "" : ((DateTime)Value).ToShortDateString();
            return html.TextBox("", dateTimeStr, new {datepicker = true});
        }

        public bool GetIDisplayTemplateImplemented() { return true; }
        public MvcHtmlString DisplayTemplate(HtmlHelper html)
        {
            var dateTimeStr = (Value == null) ? "" : ((DateTime)Value).ToShortDateString();
            return MvcHtmlString.Create(dateTimeStr);
        }

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            string key = bindingContext.ModelName;
            ValueProviderResult val = bindingContext.ValueProvider.GetValue(key);
            string attemptedValue;
            if (val == null || string.IsNullOrEmpty(val.AttemptedValue))
            {
                if (bindingContext.ModelMetadata.IsRequired) bindingContext.ModelState.AddModelError(key, string.Format("The field {0} is required", bindingContext.ModelMetadata.DisplayName ?? bindingContext.ModelMetadata.PropertyName));
                // ReSharper disable RedundantAssignment
                attemptedValue = "";
                // ReSharper restore RedundantAssignment
                Value = null;
            }
            else
            {
                attemptedValue = val.AttemptedValue;
                try
                {
                    Value = DateTime.Parse(attemptedValue);
                }
                catch(FormatException)
                {
                    Value = null;
                    bindingContext.ModelState.AddModelError(key, string.Format("The field {0} is invalid", bindingContext.ModelMetadata.DisplayName ?? bindingContext.ModelMetadata.PropertyName));
                }
            }

            bindingContext.ModelState.SetModelValue(key, val);

            var existingModel = (DateTimeFormModel)bindingContext.Model;
            if (existingModel != null)
            {
                existingModel.Value = Value;
                return existingModel;
            }
            return this;
        }
    }

    public static class FormModelDateTimeExtensions
    {
        public static DateTime? GetValue(this DateTimeFormModel me)
        {
            return me.Value;
        }

        public static DateTimeFormModel SetEnumValue(this DateTimeFormModel me, DateTime? value)
        {
            me.Value = value;
            return me;
        }
    }
}
